"""
文件名: users.py
描述: 用户管理API路由

本模块包含以下主要功能：
1. 用户信息查询和更新
2. 用户统计信息
3. 用户订阅同步
4. 用户设置管理
5. 用户数据导出

依赖模块:
   - fastapi: Web框架路由
   - services: 用户服务
   - models: 数据模型

使用示例:
   >>> GET /users/me - 获取当前用户信息
   >>> PUT /users/me - 更新用户信息
   >>> GET /users/me/stats - 获取用户统计
   >>> POST /users/me/sync - 同步用户订阅

注意事项:
   - 用户只能操作自己的数据
   - 敏感信息不能暴露
   - 同步操作要异步处理
   - 更新要验证权限

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import Dict, Any, Optional
import uuid

from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from pydantic import BaseModel

from src.api.dependencies import (
    get_current_user,
    get_user_service,
    get_category_service,
    get_rate_limit_info,
)
from src.core.logger import get_logger
from src.models.user import User, UserUpdate, UserStats, UserProfile
from src.services.user_service import UserService
from src.services.category_service import CategoryService
from src.utils.exceptions import (
    DatabaseException,
    ValidationException,
    AuthenticationException,
)

logger = get_logger(__name__)

router = APIRouter()


class UserUpdateRequest(BaseModel):
    """用户更新请求模型"""
    name: Optional[str] = None
    avatar: Optional[str] = None


class SyncResponse(BaseModel):
    """同步响应模型"""
    status: str
    message: str
    stats: Optional[Dict[str, Any]] = None


@router.get("/me", response_model=UserProfile, summary="获取当前用户信息")
async def get_current_user_profile(
    current_user: User = Depends(get_current_user),
) -> UserProfile:
    """
    获取当前用户的个人资料
    
    Returns:
        UserProfile: 用户个人资料
    """
    return UserProfile(
        id=current_user.id,
        name=current_user.name,
        avatar=current_user.avatar,
        is_premium=current_user.is_premium,
        total_channels=current_user.total_channels,
        total_categories=current_user.total_categories,
        created_at=current_user.created_at,
    )


@router.put("/me", response_model=UserProfile, summary="更新用户信息")
async def update_current_user(
    user_update: UserUpdateRequest,
    current_user: User = Depends(get_current_user),
    user_service: UserService = Depends(get_user_service),
    rate_limit: Dict[str, str] = Depends(get_rate_limit_info),
) -> UserProfile:
    """
    更新当前用户的个人信息
    
    Args:
        user_update: 用户更新数据
        
    Returns:
        UserProfile: 更新后的用户资料
    """
    try:
        # 创建更新数据
        update_data = UserUpdate()
        if user_update.name is not None:
            update_data.name = user_update.name
        if user_update.avatar is not None:
            update_data.avatar = user_update.avatar
        
        # 更新用户信息
        updated_user = await user_service.update_user(current_user.id, update_data)
        if not updated_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        logger.info(
            f"用户信息更新成功",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        
        return UserProfile(
            id=updated_user.id,
            name=updated_user.name,
            avatar=updated_user.avatar,
            is_premium=updated_user.is_premium,
            total_channels=updated_user.total_channels,
            total_categories=updated_user.total_categories,
            created_at=updated_user.created_at,
        )
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(
            f"更新用户信息失败: {e}",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新用户信息失败"
        )


@router.get("/me/stats", response_model=UserStats, summary="获取用户统计信息")
async def get_user_statistics(
    current_user: User = Depends(get_current_user),
    user_service: UserService = Depends(get_user_service),
) -> UserStats:
    """
    获取当前用户的统计信息
    
    包括订阅频道数、分类数、缓存视频数等统计数据。
    
    Returns:
        UserStats: 用户统计信息
    """
    try:
        stats = await user_service.get_user_stats(current_user.id)
        if not stats:
            # 如果没有统计数据，返回默认值
            stats = UserStats(
                total_channels=current_user.total_channels,
                total_categories=current_user.total_categories,
                total_videos_cached=0,
                last_sync_at=current_user.last_sync_at,
                sync_status="never",
            )
        
        return stats
        
    except Exception as e:
        logger.error(f"获取用户统计失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取统计信息失败"
        )


@router.post("/me/sync", response_model=SyncResponse, summary="同步用户订阅")
async def sync_user_subscriptions(
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_user),
    user_service: UserService = Depends(get_user_service),
    category_service: CategoryService = Depends(get_category_service),
    rate_limit: Dict[str, str] = Depends(get_rate_limit_info),
) -> SyncResponse:
    """
    同步用户的YouTube订阅频道
    
    此操作会从YouTube API获取用户的最新订阅列表，
    并更新本地数据库中的频道信息。
    
    Returns:
        SyncResponse: 同步结果
    """
    try:
        # 检查用户是否有有效的认证凭据
        credentials = await user_service.get_user_credentials(current_user)
        if not credentials:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户认证凭据无效，请重新登录"
            )
        
        # 如果是新用户，先初始化默认分类
        if current_user.total_categories == 0:
            await category_service.init_default_categories(current_user.id)
            logger.info(f"为新用户初始化默认分类", user_id=str(current_user.id))
        
        # 异步执行同步任务
        def sync_task():
            import asyncio
            asyncio.create_task(user_service.sync_user_subscriptions(current_user))
        
        background_tasks.add_task(sync_task)
        
        logger.info(
            f"用户订阅同步任务已启动",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        
        return SyncResponse(
            status="started",
            message="同步任务已启动，请稍后查看结果"
        )
        
    except AuthenticationException as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=str(e)
        )
    except Exception as e:
        logger.error(
            f"启动同步任务失败: {e}",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="启动同步任务失败"
        )


@router.get("/me/sync/status", summary="获取同步状态")
async def get_sync_status(
    current_user: User = Depends(get_current_user),
) -> Dict[str, Any]:
    """
    获取用户订阅同步状态
    
    Returns:
        Dict[str, Any]: 同步状态信息
    """
    # 根据最后同步时间判断同步状态
    sync_status = "never"
    if current_user.last_sync_at:
        from datetime import datetime, timedelta
        time_since_sync = datetime.utcnow() - current_user.last_sync_at
        if time_since_sync.total_seconds() < 300:  # 5分钟内
            sync_status = "recent"
        elif time_since_sync.total_seconds() < 3600:  # 1小时内
            sync_status = "outdated"
        else:
            sync_status = "old"
    
    return {
        "sync_status": sync_status,
        "last_sync_at": current_user.last_sync_at,
        "total_channels": current_user.total_channels,
        "total_categories": current_user.total_categories,
        "is_syncing": False,  # 这里可以检查是否有正在进行的同步任务
    }


@router.delete("/me", summary="删除用户账户")
async def delete_user_account(
    current_user: User = Depends(get_current_user),
    user_service: UserService = Depends(get_user_service),
    rate_limit: Dict[str, str] = Depends(get_rate_limit_info),
) -> Dict[str, str]:
    """
    删除当前用户账户（软删除）
    
    注意：此操作不可逆，会删除用户的所有数据。
    
    Returns:
        Dict[str, str]: 删除结果
    """
    try:
        success = await user_service.soft_delete_user(current_user.id)
        if not success:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        logger.info(
            f"用户账户删除成功",
            user_id=str(current_user.id),
            email=current_user.email,
            client_ip=rate_limit["client_ip"]
        )
        
        return {"message": "账户删除成功"}
        
    except Exception as e:
        logger.error(
            f"删除用户账户失败: {e}",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="删除账户失败"
        )


@router.get("/me/export", summary="导出用户数据")
async def export_user_data(
    current_user: User = Depends(get_current_user),
    rate_limit: Dict[str, str] = Depends(get_rate_limit_info),
) -> Dict[str, Any]:
    """
    导出用户数据（GDPR合规）
    
    Returns:
        Dict[str, Any]: 用户数据导出
    """
    try:
        # 导出用户基本信息（不包含敏感数据）
        export_data = {
            "user_info": {
                "id": str(current_user.id),
                "name": current_user.name,
                "email": current_user.email,
                "created_at": current_user.created_at.isoformat(),
                "last_login_at": current_user.last_login_at.isoformat() if current_user.last_login_at else None,
                "is_premium": current_user.is_premium,
            },
            "statistics": {
                "total_channels": current_user.total_channels,
                "total_categories": current_user.total_categories,
                "last_sync_at": current_user.last_sync_at.isoformat() if current_user.last_sync_at else None,
            },
            "export_info": {
                "exported_at": datetime.utcnow().isoformat(),
                "export_format": "json",
                "data_version": "1.0",
            }
        }
        
        logger.info(
            f"用户数据导出成功",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        
        return export_data
        
    except Exception as e:
        logger.error(
            f"导出用户数据失败: {e}",
            user_id=str(current_user.id),
            client_ip=rate_limit["client_ip"]
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="导出数据失败"
        )